import hypermedia.video.*;

OpenCV opencv;
PImage img;
PImage imageFile;
PImage edgeImg;
PImage blurSum;
boolean clicked = false;
boolean swapVid = false;


void setup() {
  
  size( 640, 480 );
  opencv = new OpenCV( this );
  
  /*imageFile = loadImage("cat.jpg");
  opencv.allocate(imageFile.width, imageFile.height);
  opencv.copy(imageFile);*/
  
  //Loading in from a specified movie clip in the same folder as the sketch
  opencv.movie( "planetearth.mov", width/2, height/2);
  
  //Loading from the webcam
  //opencv.capture(width, height);
  
  //Uncomment this if you only want the effect on one frame
  //noLoop();
}

void draw() {
  background(255);
   // read a new frame and puts into the buffer (for video only) - comment this out if reading from an image!
  opencv.read();
  //processing can go after this
  
  //draws original
  image(opencv.image(),0,0,320,240);
  textSize(32);
  text("original video", 10, 30);

  
  blurSum = createImage(opencv.image().width, opencv.image().height, ALPHA);
  int blurNums = 3;
  for(int b = 0; b < blurNums; b++){
    //runs the edge detector and draws the edges
    opencv.blur(opencv.GAUSSIAN,3);
    edgeDetector(opencv.image());
    edgeImg.loadPixels();
    for(int e=0; e < edgeImg.pixels.length; e++) {
      color col = edgeImg.pixels[e];
      float val = red(col) * 2*b;
      edgeImg.pixels[e] = color(val, 0, 0);
    }
    blurSum.blend(edgeImg, 0, 0, edgeImg.width, edgeImg.height, 0, 0, blurSum.width, blurSum.height, ADD);
  }
  
  //smooths some edges with median blur
  opencv.copy(blurSum);
  //opencv.blur(opencv.MEDIAN,3);
  opencv.threshold(25, 255, opencv.THRESH_TOZERO);
  blurSum.copy(opencv.image(), 0,0,320,240,0,0,320,240); //= opencv.image();
  blurSum.loadPixels();
  
  //turns the RGB into an ALPHA to allow transparency
  for(int c = 0; c < blurSum.pixels.length; c++){
    blurSum.pixels[c] = color(0,0,0,red(blurSum.pixels[c]));
  }
  
  opencv.restore();
  
  //comment this out if reading from a video
  //opencv.copy(imageFile);

  //limits number of colors used in the image
  PImage temp = opencv.image();
  temp.filter(POSTERIZE, 9);
  opencv.copy(temp);
  
  //runs multiple passes of bilateral filter (blurs but preserves edges)
  for(int a = 0; a < 5; a++)
    opencv.blur(opencv.BILATERAL,30,30,0,0);

  //draws bilateral blurred image
  //Need to comment this out to see JUST edge detected lines
  image(opencv.image(),0,240,320,240);
  textSize(32);
  text("post bilateral blur", 10, 270);
  
  //draws edge image
  image(blurSum, 320, 0, 320, 240);
  textSize(32);
  fill(255,0,0);
  text("post edge detection", 330, 30);
  fill(255,255,255);
   
  //draws final project
  image(opencv.image(),320,240,320,240);
  image(blurSum, 320, 240, 320, 240);
  textSize(32);
  text("blur and edges", 330, 270);
  
  g.removeCache(edgeImg);
  g.removeCache(blurSum);
  
  //exports pngs of each frame to the sketch folder
  //saveFrame("######.png");
}

//can scrub dragging mouse along horizontal direction
void mouseDragged() {
  float time = mouseX/float(width);
  opencv.jump( time );
}


//hit tab to switch between specified movie clip and webcam
//hit space to play/pause
void keyPressed() {
  if(keyCode == 9){
    swapVid = !swapVid;
    if(swapVid){
      //Loading from the webcam
      opencv.capture(width/2, height/2);
    }
    else{
      //Loading in from a specified movie clip in the same folder as the sketch
      opencv.movie( "planetearth.mov", width/2, height/2);
    }    
  }
  if(keyCode == 32){
    if(clicked){
      noLoop();
    }
    else if(!clicked){    
      loop();
    }
  clicked = !clicked;
  }
}

void edgeDetector(PImage img){
  img.loadPixels();
  
  // Create an opaque image of the same size as the original
  edgeImg = createImage(img.width, img.height, RGB);
  
  //Uncomment this and the code below to see JUST the black edge detected lines on a yellow background
   //background(255, 204, 0); 
   
  // Loop through every pixel in the image.
  for (int y = 1; y < img.height; y++) { // Skip top and bottom edges
    for (int x = 1; x < img.width; x++) { // Skip left and right edges
    
       // Pixel location and color
      int loc = x + y*img.width;
      color pix = img.pixels[loc];
      
      // Pixel to the left location and color
      int leftLoc = (x - 1) + y*img.width;
      color leftPix = img.pixels[leftLoc];
      
      //Top px location and color
      int topLoc = x + (y-1)*img.width;
      color topPix = img.pixels[topLoc];
      
      // New color is difference between pixel and left neighbor
      float diff2 = abs(brightness(pix) - brightness(topPix));
      float diff = abs(brightness(pix) - brightness(leftPix));
      diff = Math.max(diff, diff2);
      
      //this draws the edge detected lines in BLACK to a new image
      /*if(diff>25)
        edgeImg.pixels[loc] = color(255, 0, 0);
      else*/
        edgeImg.pixels[loc] = color(diff,0,0); 
    }
  }
  // State that there are changes to edgeImg.pixels[]
  edgeImg.updatePixels();
   // Uncomment this if you want to see JUST the edge detected lines
  //image(edgeImg, 0, 0, 640, 480);
}
